package cn.com.youjile.handler;

import cn.com.youjile.client.GeneralClient;
import cn.com.youjile.config.InitConfig;
import cn.com.youjile.entity.MsgInfo;
import cn.com.youjile.init.ApplicationRunnerImpl;
import cn.com.youjile.listener.ConnListener;
import cn.com.youjile.observer.MsgSubject;
import cn.com.youjile.protobuf.ResultInfo;
import cn.com.youjile.utils.MsgInfoFactory;
import cn.com.youjile.utils.MsgNumUtil;
import cn.com.youjile.utils.ResultUtil;
import cn.com.youjile.utils.SpringUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @Author youjile
 * @CreateDate 2021/3/12
 * @Describe 客户端
 */
public class GeneralClientHandler extends ChannelInboundHandlerAdapter {

    private static final Logger logger = LoggerFactory.getLogger(GeneralClientHandler.class);

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        logger.debug("general client : ctx = [" + ctx + "], msg = [" + msg.toString() + "]");
        if (msg instanceof MsgInfo) {
            /**
             * 这里加入客户端收到消息时的处理逻辑
             */
            MsgInfo msgInfo = (MsgInfo) msg;
            MsgSubject.getInstance().setState(ctx, msgInfo);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("general client启动成功！");
        ConnListener.connCount = InitConfig.connCountTotal;         // client客户端连接成功，还原断连重连次数
        GeneralClient.serverChannel = ctx.channel();
        /**
         * 这里可以加入客户端上线的通知
         */
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //这里需要配合ConnectionListener来实现
        ctx.channel().eventLoop().schedule(new Runnable() {
            @Override
            public void run() {
                ApplicationRunnerImpl ari = SpringUtil.getBean(ApplicationRunnerImpl.class);
                logger.error("服务端链接断开，开始重连操作...");
                try {
                    new GeneralClient(InitConfig.host, InitConfig.clientPort).run();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 3 , TimeUnit.SECONDS);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if(evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent)evt;
            if (event.state().equals(IdleState.READER_IDLE)) {
                logger.debug("长时间没收到服务器端心跳响应");
                //可以考虑重新连接服务器
            } else if (event.state().equals(IdleState.WRITER_IDLE)) {
                logger.debug("长时间没有向服务器端发送心跳，向服务器发送一条心跳。");
                //发送一次心跳
                byte[] success = ResultUtil.success("I am alive");
                MsgInfo msgInfo = MsgInfoFactory.buildMessageInfo(MsgNumUtil.success, success);
                ctx.writeAndFlush(msgInfo);
            } else if (event.state().equals(IdleState.ALL_IDLE)) {
                byte[] success = ResultUtil.success("I am alive");
                MsgInfo msgInfo = MsgInfoFactory.buildMessageInfo(MsgNumUtil.success, success);
                ctx.writeAndFlush(msgInfo);
                logger.debug("[client] 所有心跳事件都被触发。");
            }
        }
    }



}
